package sebastiankerckhof.scene.geometry;

import sebastiankerckhof.math.Point3f;
import sebastiankerckhof.render.raytrace.Ray;

public class BBox {
	public Point3f min, max;

	public BBox(Point3f min, Point3f max) {
		this.min = min;
		this.max = max;
	}

	public BBox combine(BBox other) {
		float x, y, z;
		
		x = Math.min(this.min.x, other.min.x);
		y = Math.min(this.min.y, other.min.y);
		z = Math.min(this.min.z, other.min.z);
		Point3f min = new Point3f(x, y, z);
		
		x = Math.max(this.max.x, other.max.x);
		y = Math.max(this.max.y, other.max.y);
		z = Math.max(this.max.z, other.max.z);
		Point3f max = new Point3f(x, y, z);
		
		return new BBox(min, max);
	}


	public float getMidPoint(int axis){
		return (min.get(axis)+max.get(axis) / 2f);
	}

	public boolean hit(Ray ray, float t0, float t1) {
		float xmin, xmax, ymin, ymax, zmin, zmax, d;

		d = 1 / ray.direction.x;
		if (d >= 0) {
			xmin = (min.x - ray.origin.x) * d;
			xmax = (max.x - ray.origin.x) * d;
		} else {
			xmin = (max.x - ray.origin.x) * d;
			xmax = (min.x - ray.origin.x) * d;
		}

		d = 1 / ray.direction.y;
		if (d >= 0) {
			ymin = (min.y - ray.origin.y) * d;
			ymax = (max.y - ray.origin.y) * d;
		} else {
			ymin = (max.y - ray.origin.y) * d;
			ymax = (min.y - ray.origin.y) * d;
		}
		d = 1 / ray.direction.z;
		if (d >= 0) {
			zmin = (min.z - ray.origin.z) * d;
			zmax = (max.z - ray.origin.z) * d;
		} else {
			zmin = (max.z - ray.origin.z) * d;
			zmax = (min.z - ray.origin.z) * d;
		}

		if (xmin > ymax || ymin > xmax || xmin > zmax || zmin > xmax || zmin > ymax || ymin > zmax)
			return false;
		return true;
	}

	@Override
	public boolean equals(Object o){
		BBox b = (BBox) o;
		return b.min.equals(min) && b.max.equals(max);
	}

}
